/* 
  Copyright (c) Whitemice Consulting, 2007, 2008, 2009
  Adam Tauno Williams <awilliam@whitemice.org>
  License: MIT/X11

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/
using System;
using System.Collections;
using System.Collections.Generic;

namespace Whitemice.ZOGI.RPC2
{
  /// <summary>
  /// The ZOGIDecode class is used by entity objects to retrieve values from the
  /// dictionary produced by RpcWasher from the XmlRpcStruct recieved from the
  /// server.
  /// </summary>
  public abstract class ZOGIDecoder
  {
    /// <summary>
    /// Checks if the dictionary contains the requested key.
    /// </summary>
    /// <exception cref="Whitemice.ZOGI.MissingMandatoryKeyException">
    /// Thrown if the dictionary lacks the specified key.
    /// </exception>    
    /// <param name="_hash">
    /// A <see cref="IDictionary<string, object>"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="System.Boolean"/>
    /// </returns>
    private static bool HasKey(IDictionary<string, object> _hash, string _key)
    {
      if (_hash.ContainsKey(_key))
        return true;
      throw new MissingMandatoryKeyException(_hash, _key);
    } /* end HasKey */
    
    /// <summary>
    /// Retrieves the specified value from the dictionary as an Int32
    /// </summary>
    /// <exception cref="Whitemice.ZOGI.ZOGIProtocolException">
    /// Thrown if the specified value is not an integer.
    /// </exception>
    /// <param name="_hash">
    /// A <see cref="System.Collections.Generic.IDictionary"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="System.Int32"/>
    /// </returns>
    public static int AsInt32(IDictionary<string, object> _hash, string _key)
    {
      HasKey(_hash, _key);
      try
      {
        if (_hash[_key] is System.String)
          if ((_hash[_key] as System.String).Length == 0)
            return 0;
        return Convert.ToInt32(_hash[_key]);
      } catch (Exception _exception)
        {
          throw new ZOGIProtocolException(
                      string.Format("Expected key {0} to be an integer.",
                        _key),
                      _exception);
        }
    } /* end AsInt32 */
    
    /// <summary>
    /// Retrieves the specified value from the dictionary as a string
    /// </summary>
    /// </summary>
    /// <param name="_hash">
    /// A <see cref="System.Collections.Generic.IDictionary"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="System.String"/>
    /// </returns>    
    public static string AsString(IDictionary<string, object> _hash, string _key)
    {
      HasKey(_hash, _key);
      return _hash[_key].ToString();
    } /* end AsString */
    
    /// <summary>
    /// Retrieves the specified value from the dictionary as an array of
    /// strings.
    /// </summary>
    /// <param name="_hash">
    /// A <see cref="System.Collections.Generic.IDictionary"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="System.String"/>
    /// </returns>    
    public static string[] AsArrayOfStrings(IDictionary<string, object> _hash, string _key)
    {
      HasKey(_hash, _key);
      return (_hash[_key] as string[]);
    } /* end AsArrayOfStrings */
    
    /// <summary>
    /// Retrieves the specified value from the dictionary as an array of
    /// integers.
    /// </summary>
    /// <param name="_hash">
    /// A <see cref="System.Collections.Generic.IDictionary"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="System.Int32"/>
    /// </returns>
    public static int[] AsArrayOfInts(IDictionary<string, object> _hash, string _key)
    {
      HasKey(_hash, _key);
      return (_hash[_key] as int[]);
    } /* end AsArrayOfInts */
    
    /// <summary>
    /// Retrieves the specified value from the dictionary as a DateTime
    /// </summary>
    /// <param name="_hash">
    /// A <see cref="System.Collections.Generic.IDictionary"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="DateTime"/>
    /// </returns>    
    public static DateTime AsDateTime(IDictionary<string, object> _hash, string _key)
    {
      HasKey(_hash, _key);
      if (_hash[_key] is System.String)
        if ((_hash[_key] as System.String).Length == 0)
          return DateTime.MinValue;
      return Convert.ToDateTime(_hash[_key]);
    } /* end AsDateTime */
    
    /// <summary>
    /// Retrieves the specified value from the dictionary as a bool
    /// </summary>
    /// <param name="_hash">
    /// A <see cref="System.Collections.Generic.IDictionary"/>
    /// </param>
    /// <param name="_key">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="System.Boolean"/>
    /// </returns>
    public static bool AsBoolean(IDictionary<string, object> _hash, string _key)
    {
      HasKey(_hash, _key);
      if (_hash[_key] is System.String)
        if ((_hash[_key] as System.String).Length == 0)
          return false;
      if (Convert.ToInt32(_hash[_key]) > 0)
        return true;
      return false;
    }
  }
}